home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 101 / CD-ROM 101.iso / compl / maya5ple / Install_MayaPLE5_English.exe / Maya / Data1.cab / AEgenericPerParticle.mel < prev    next >
Encoding:
Text File  |  2003-07-17  |  25.3 KB  |  1,075 lines

  1. // Copyright (C) 1997-2002 Alias|Wavefront,
  2. // a division of Silicon Graphics Limited.
  3. //
  4. // The information in this file is provided for the exclusive use of the
  5. // licensees of Alias|Wavefront.  Such users have the right to use, modify,
  6. // and incorporate this code into other products for purposes authorized
  7. // by the Alias|Wavefront license agreement, without fee.
  8. //
  9. // ALIAS|WAVEFRONT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  10. // INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  11. // EVENT SHALL ALIAS|WAVEFRONT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  12. // CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  13. // DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  14. // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. // PERFORMANCE OF THIS SOFTWARE.
  16. //
  17. //
  18. //  Alias|Wavefront Script File
  19. //
  20. //  Creation Date:    July 11, 1997
  21. //  Author:    rh
  22. //
  23. //  Procedure Name:
  24. //        AEgenericPerParticle
  25. //
  26. //  Description:
  27. //        Create attribute editor controls for per particle attributes.
  28. //
  29. //  Input Value:
  30. //        nodeAttr ("nodeName.attributeName")
  31. //
  32. //  Output Value:
  33. //        None
  34. //
  35.  
  36.  
  37. global string    $gAEgenericSuppress[] = 
  38.                     {
  39.                         "acceleration",
  40.                         "velocity",
  41.                         "position",
  42.                         "mass",
  43.                         "ageNormalized",
  44.                         "inputForce",
  45.                         "uvSetTweakLocation"
  46.                     };
  47.  
  48. //  ========== AEgenericReset ==========
  49. //
  50. //  Description:
  51. //        Locate the parent column layout and the enclosing frame
  52. //        layout. This is needed later to add/delete children and
  53. //        to open/close the frame layout. At any time, the parents
  54. //        might get deleted, so we always need to verify.
  55. //
  56.  
  57. proc  AEgenericReset()
  58. {
  59.  
  60.     global string    $gAEgenericColumnLayout;
  61.     global string    $gAEgenericFrameLayout;
  62.     string            $currentParent = `setParent -q`;
  63.  
  64.  
  65.     if ($gAEgenericColumnLayout != $currentParent)
  66.     {
  67.         // There is a new parent. Save the new colum layout
  68.         // parent, and find the enclosing frame layout.
  69.         //
  70.         $gAEgenericColumnLayout = $currentParent;
  71.  
  72.         int        $columnLytCnt = size( $gAEgenericColumnLayout );
  73.         int        $count = 0;
  74.  
  75.         for ($i = $columnLytCnt; $i >= 1; $i--)
  76.         {
  77.             if (substring( $gAEgenericColumnLayout, $i, $i ) == "|") $count++;
  78.  
  79.             if ($count == 2)
  80.             {
  81.                 $gAEgenericFrameLayout = substring( $gAEgenericColumnLayout, 1, ($i - 1) );
  82.                 break;
  83.             }
  84.         }
  85.     }
  86.  
  87.  
  88. }  // AEgenericReset //
  89.  
  90.  
  91.  
  92. //  ========== AEokayAttr ==========
  93. //
  94. //  Description:
  95. //        Check the given attribute with the list of
  96. //        attributes to suppress.
  97. //
  98.  
  99. proc int  AEokayAttr( string $shapeName, string $attrName )
  100. {
  101.     global string    $gAEgenericSuppress[];
  102.     int                $count = size( $gAEgenericSuppress );
  103.  
  104.     // First check whether this is among our fixed list of
  105.     // attributes which we suppress, but then make appear
  106.     // at a fixed place at the top of the list.
  107.     //
  108.     for ($i = 0; $i < $count; $i++)
  109.     {
  110.         if ($attrName == $gAEgenericSuppress[$i])
  111.         {
  112.             return( 0 );
  113.         }
  114.     }
  115.  
  116.     // Also check whether this attribute has been marked HIDDEN.
  117.     // These don't appear in the list at all.
  118.     // The listAttr command below will return something if this
  119.     // attribute is visible. 
  120.     //
  121.     string $returnName[] = `listAttr -v -w -st $attrName $shapeName`;
  122.     if (size($returnName) == 0)
  123.         return 0;
  124.  
  125.     return( 1 );
  126.  
  127.  
  128. }  // AEokayAttr //
  129.  
  130.  
  131.  
  132. //  ========== AEdynAryAttr ==========
  133. //
  134. //  Description:
  135. //        Return a sorted list of dynamic attributes on the
  136. //        particle shape. This list is filtered to remove the
  137. //        hidden attributes that the user should not be using.
  138. //        Each attribute has its type appended to it. For example,
  139. //        example, "radiusPP.Float", "rgbPP.Vector". This is
  140. //        used by the component editor.
  141. //
  142.  
  143. proc  AEdynAryAttr( string $node, string $attrList[] )
  144. {
  145.  
  146.     // Clear the array in case there are no attributes.
  147.     //
  148.     int        $attrCnt = 0;
  149.  
  150.     clear( $attrList );
  151.  
  152.  
  153.     // Create place holders for the static attributes
  154.     // which will be added later.
  155.     //
  156.     $attrList[$attrCnt++] = "aaaa";
  157.     $attrList[$attrCnt++] = "aaaa";
  158.     $attrList[$attrCnt++] = "aaaa";
  159.     $attrList[$attrCnt++] = "aaaa";
  160.     $attrList[$attrCnt++] = "aaaa";
  161.     $attrList[$attrCnt++] = "aaaa";
  162.     $attrList[$attrCnt++] = "aaaa";
  163.  
  164.  
  165.     // Make a list of per particle attributes. Pass
  166.     // the list through the suppression filter. While
  167.     // making the list, append the attribute type.
  168.     //
  169.     string    $dblAttrAry[] = `particle -q -ppd $node`;
  170.     string    $vecAttrAry[] = `particle -q -ppv $node`;
  171.     int        $dblAttrCnt = size( $dblAttrAry );
  172.     int        $vecAttrCnt = size( $vecAttrAry );
  173.  
  174.     for ($i = 0; $i < $dblAttrCnt; $i++)
  175.     {
  176.         if (AEokayAttr( $node, $dblAttrAry[$i] ))
  177.         {
  178.             $attrList[$attrCnt++] = ($dblAttrAry[$i]+".Float");
  179.         }
  180.     }
  181.  
  182.     for ($i = 0; $i < $vecAttrCnt; $i++)
  183.     {
  184.         if (AEokayAttr( $node, $vecAttrAry[$i] ))
  185.         {
  186.             $attrList[$attrCnt++] = ($vecAttrAry[$i]+".Vector");
  187.         }
  188.     }
  189.  
  190.  
  191.     // Finally, sort the list.
  192.     //
  193. //    $attrList = sort( $attrList );
  194.  
  195.  
  196.     // After the list has been sorted, add the static
  197.     // attributes to the beginning of the list.
  198.     //
  199.     $attrList[0] = "position.Vector";
  200.     $attrList[1] = "rampPosition.Vector";
  201.     $attrList[2] = "velocity.Vector";
  202.     $attrList[3] = "rampVelocity.Vector";
  203.     $attrList[4] = "acceleration.Vector";
  204.     $attrList[5] = "rampAcceleration.Vector";
  205.     $attrList[6] = "mass.Double";
  206.  
  207.  
  208. }  // AEdynAryAttr //
  209.  
  210.  
  211.  
  212. //  ========== AEgenericIsExpression ==========
  213. //
  214. //  Description:
  215. //        Inspect the attribute connection to see if it
  216. //        is an expression connection. The format
  217. //        of the input string is: nodeName.attName.
  218. //
  219.  
  220. proc int  AEgenericIsExpression( string $attrConnection )
  221. {
  222.  
  223.     if (match( "output", $attrConnection ) == "")
  224.     {
  225.         return( 0 );
  226.     }
  227.     else
  228.     {
  229.         return( 1 );
  230.     }
  231.  
  232. }  // AEgenericIsExpression //
  233.  
  234.  
  235.  
  236. //  ========== AEgenericIsArrayMapper ==========
  237. //
  238. //  Description:
  239. //        Inspect the attribute connection to see if it
  240. //        is connected to an array mapper node. The format
  241. //        of the input string is: nodeName.attName.
  242. //
  243.  
  244. proc int  AEgenericIsArrayMapper( string $attrConnection )
  245. {
  246.     string    $words[];
  247.  
  248.     tokenize( $attrConnection, ".", $words );
  249.  
  250.     if (`nodeType $words[0]` == "arrayMapper")
  251.     {
  252.         return( 1 );
  253.     }
  254.     else
  255.     {
  256.         return( 0 );
  257.     }
  258.  
  259.  
  260. }  // AEgenericIsArrayMapper //
  261.  
  262.  
  263.  
  264. //  ========== AEgenericConnectText ==========
  265. //
  266. //  Description:
  267. //        Return a text description of what this attribute
  268. //        is connected to. If there is an upstream connection,
  269. //        then this gets placed in the textfield. If there are
  270. //        (only) one or more downstream connections, then the
  271. //        special "-> " string is used. Otherwise the textfield
  272. //        is blank.
  273. //
  274.  
  275. global proc string  AEgenericConnectText( string $nodeName, string $attrName )
  276. {
  277.     string    $cnctAry[];
  278.  
  279.  
  280.     // Check for upstream connections.
  281.     //
  282.     $cnctAry = `listConnections -s true -d false -p true ($nodeName+"."+$attrName)`;
  283.  
  284.     if (size( $cnctAry ))
  285.     {
  286.         if (AEgenericIsExpression( $cnctAry[0] ))
  287.         {
  288.             // Special case for expressions.
  289.             //
  290.             return( "Expression..." );
  291.         }
  292.         else
  293.         {
  294.             // Show the upstream connection.
  295.             //
  296.             return( "<- "+$cnctAry[0] );
  297.         }
  298.     }
  299.  
  300.     // Check for downstream connections.
  301.     //
  302.     else
  303.     {
  304.         $cnctAry = `listConnections -s false -d true ($nodeName+"."+$attrName)`;
  305.         
  306.         if (size( $cnctAry ))
  307.         {
  308.             return( "->..." );
  309.         }
  310.         else
  311.         {
  312.             return( "" );
  313.         }
  314.     }
  315.  
  316.  
  317. }  // AEgenericConnectText //
  318.  
  319.  
  320.  
  321. //  ========== AEgenericBreakConnection ==========
  322. //
  323. //  Description:
  324. //        Break the connection between the particle shape
  325. //        and the array mapper node. Clear the textfield.
  326. //
  327.  
  328. global proc  AEgenericBreakConnection( string $node, string $srcAttr, string $dstAttr )
  329. {
  330.     
  331.     disconnectAttr $srcAttr $dstAttr;
  332.     AEgenericUpdateAllTextfields( $node );
  333.  
  334.  
  335. }  // AEgenericBreakConnection //
  336.  
  337.  
  338.  
  339. //  ========== AEgenericBreakAllConnection ==========
  340. //
  341. //  Description:
  342. //        Break all the connections between the particle shape
  343. //        and the array mapper node. Clear the textfield.
  344. //
  345.  
  346. global proc  AEgenericBreakAllConnections( string $psNode, string $amNode )
  347. {
  348.     string    $downCnctAry[];
  349.     int        $downCnctCnt;
  350.     string    $upCnctAry[];
  351.     string    $words[];
  352.  
  353.     
  354.     // Break all the downstream connections from the array
  355.     // mapper node to the particle shape node.
  356.     //
  357.     $downCnctAry = `listConnections -s false -d true -p true $amNode`;
  358.     $downCnctCnt = size( $downCnctAry );
  359.  
  360.     for ($i = 0; $i < $downCnctCnt; $i++)
  361.     {
  362.         tokenize( $downCnctAry[$i], ".", $words );
  363.  
  364.         if ($words[0] == $psNode)
  365.         {
  366.             $upCnctAry = `listConnections -s true -d false -p true $downCnctAry[$i]`;
  367.             disconnectAttr $upCnctAry[0] $downCnctAry[$i];
  368.         }
  369.     }
  370.  
  371.  
  372.     // Break all the downstream connections from the particle
  373.     // shape to the array mapper node.
  374.     //
  375.     $downCnctAry = `listConnections -s false -d true -p true $psNode`;
  376.     $downCnctCnt = size( $downCnctAry );
  377.  
  378.     for ($i = 0; $i < $downCnctCnt; $i++)
  379.     {
  380.         tokenize( $downCnctAry[$i], ".", $words );
  381.  
  382.         if ($words[0] == $amNode)
  383.         {
  384.             $upCnctAry = `listConnections -s true -d false -p true $downCnctAry[$i]`;
  385.             disconnectAttr $upCnctAry[0] $downCnctAry[$i];
  386.         }
  387.     }
  388.  
  389.  
  390.     // Update the attribute editor.
  391.     //
  392.     AEgenericUpdateAllTextfields( $psNode );
  393.  
  394.  
  395. }  // AEgenericBreakAllConnection //
  396.  
  397.  
  398.  
  399. //  ========== AEgenericDeleteMapper ==========
  400. //
  401. //  Description:
  402. //        Break all connections to the mapper node, and then
  403. //        delete the mapper node. If the ramp node is left
  404. //        without any connections, delete it also.
  405. //
  406.  
  407. global proc  AEgenericDeleteMapper( string $psNode, string $amNode, string $rowLyt )
  408. {
  409.     string    $cnctAry[];
  410.     string    $rampNode;
  411.  
  412.  
  413.     // Get the ramp node.
  414.     //
  415.     $cnctAry = `listConnections -s true -d false ($amNode+".computeNode")`;
  416.  
  417.     if (size( $cnctAry ) == 1)
  418.     {
  419.         $rampNode = $cnctAry[0];
  420.         disconnectAttr ($rampNode+".message") ($amNode+".computeNode");
  421.  
  422.  
  423.         // If the ramp node has no more connections, then delete it.
  424.         // Note: there is always one connection for classification which
  425.         // can be ignored.
  426.         //
  427.         $cnctAry = `listConnections $rampNode`;
  428.  
  429.         if (size( $cnctAry ) <= 1)
  430.         {
  431.             delete $rampNode;
  432.         }
  433.     }
  434.  
  435.  
  436.     // Now delete the array mapper node along with any orphaned nodes.
  437.     //
  438.     delete $amNode;
  439.  
  440.  
  441.     // Update the attribute editor.
  442.     //
  443.     AEgenericUpdateAllTextfields( $psNode );
  444.  
  445.  
  446. }  // AEgenericDeleteMapper //
  447.  
  448.  
  449.  
  450. //  ========== AEconnectAttrDoIt ==========
  451. //
  452. //  Description:
  453. //        Make the attribute connection, and update the layout.
  454. //        If the source attribute does not exist, add it.
  455. //
  456.  
  457. global proc  AEconnectAttrDoIt( string $psNode, string $psAttr, string $dstNodeAttr )
  458. {
  459.  
  460.     // If the source attribute does not exists, create it.
  461.     // Always add the initial state attribute in case the
  462.     // user does a "save initial state" command.
  463.     //
  464.     if (AEattrDblExists( $psNode, $psAttr ) == 0)
  465.     {
  466.         addAttr -ln ($psAttr+"0") -dt doubleArray $psNode;
  467.         addAttr -ln $psAttr -dt doubleArray  $psNode;
  468.     }
  469.  
  470.  
  471.     // Now make the connection.
  472.     //
  473.     connectAttr ($psNode+"."+$psAttr) $dstNodeAttr;
  474.     AEgenericUpdateAllTextfields( $psNode );
  475.  
  476.  
  477. }  // AEconnectAttrDoIt //
  478.  
  479.  
  480.  
  481. //  ========== AEgenericDeleteAttr ==========
  482. //
  483. //  Description:
  484. //        Delete the given attribute. Also check for initial state
  485. //        attribute, and delete it also.
  486. //
  487.  
  488. global proc  AEgenericDeleteAttr( string $node, string $attr )
  489. {
  490.  
  491.     // Delete the given attribute.
  492.     //
  493.     deleteAttr -at $attr $node;
  494.  
  495.  
  496.     // Look for all occurrences of the initial state attribute
  497.     // and delete them.
  498.     //
  499.     string     $attrName0 = $attr+"0";
  500.     string    $attrAry[] = `listAttr -array -string $attrName0 $node`;
  501.     int        $attrCnt = size( $attrAry );
  502.  
  503.     for ($i = 0; $i < $attrCnt; $i++)
  504.     {
  505.         deleteAttr -at $attrAry[$i] $node;
  506.     }
  507.  
  508.  
  509. }  // AEgenericDeleteAttr //
  510.  
  511.  
  512.  
  513. //  ========== AEgenericUpdateOneTextfield ==========
  514. //
  515. //  Description:
  516. //        Update the textfield text for the given layout.
  517. //
  518.  
  519. global proc  AEgenericUpdateOneTextfield( string $node, string $attr, string $rowLyt )
  520. {
  521.     global string    $gAEgenericColumnLayout;
  522.     setParent $gAEgenericColumnLayout;
  523.  
  524.     string    $childAry[] = `rowLayout -q -childArray $rowLyt`;
  525.     string    $text = AEgenericConnectText( $node, $attr );
  526.  
  527.     textField -e -text $text $childAry[1];
  528.  
  529. }  // AEgenericUpdateOneTextfield //
  530.  
  531.  
  532.  
  533. //  ========== AEgenericUpdateAllTextfields ==========
  534. //
  535. //  Description:
  536. //        Update the text displayed in all the textfields based
  537. //        on the current state of the attribute. If the attribute
  538. //        is connected, display the source attribute or expression
  539. //        text. Otherwise clear the textfield. This is a convenience
  540. //        method that can be called from other editors to update
  541. //        the array attribute layout.
  542. //
  543.  
  544. global proc  AEgenericUpdateAllTextfields( string $nodeName )
  545. {
  546.     global string    $gAEgenericColumnLayout;
  547.     setParent $gAEgenericColumnLayout;
  548.  
  549.     string    $attrList[];
  550.     AEdynAryAttr( $nodeName, $attrList );
  551.  
  552.     string    $rowLytAry[] = `columnLayout -q -childArray $gAEgenericColumnLayout`;
  553.     int        $rowLytCnt = size( $rowLytAry );
  554.  
  555.     string    $childAry[];
  556.     string    $words[];
  557.  
  558.     for ($i = 0; $i < $rowLytCnt; $i++)
  559.     {
  560.         tokenize( $attrList[$i], ".", $words );
  561.         AEgenericUpdateOneTextfield( $nodeName, $words[0], $rowLytAry[$i] );
  562.     }
  563.  
  564.  
  565. }  // AEgenericUpdateAllTextfields //
  566.  
  567.  
  568.  
  569. //  ========== AEattrDblExists ==========
  570. //
  571. //  Description:
  572. //        Check if the given double array attribute already
  573. //        exists on the given particle shape.
  574. //
  575.  
  576. global proc int  AEattrDblExists( string $node, string $attr )
  577. {
  578.     string    $dblAttrAry[] = `particle -q -ppd $node`;
  579.     int        $dblAttrCnt = size( $dblAttrAry );
  580.  
  581.  
  582.     for ($i = 0; $i < $dblAttrCnt; $i++)
  583.     {
  584.         if ($attr == $dblAttrAry[$i])
  585.         {
  586.             return( 1 );
  587.         }
  588.     }
  589.  
  590.     return( 0 );
  591.  
  592.  
  593. }  // AEattrDblExists //
  594.  
  595.  
  596.  
  597. //  ========== AEcreateConnectAttr ==========
  598. //
  599. //  Description:
  600. //        Add a special case menu item to the popup menu. If the
  601. //        attribute is connected to an arrayMapper, then inspect
  602. //        arrayMapper node to see if it has an available connection.
  603. //        If so, then add a menu item which will connect a new
  604. //        attribute to the arrayMapper. Also inspect the particle
  605. //        shape, and if the attribute is not present, create it.
  606. //
  607.  
  608. proc  AEcreateConnectAttr( string $psNode, string $psAttr, string $amNode, string $amAttr )
  609. {
  610.     string    $connections[];
  611.     string    $newAttr;
  612.  
  613.  
  614.     // Check if the arrayMapper attribute is available for a connection.
  615.       //
  616.     $connections = `listConnections -s true -d false ($amNode+"."+$amAttr)`;
  617.  
  618.     if (size( $connections ) == 0)
  619.     {
  620.         // Create a new attribute name to connect to uCoordPP.
  621.         //
  622.         if ($amAttr == "uCoordPP")
  623.         {
  624.             $newAttr = substitute( "PP", $psAttr, "UPP" );
  625.             if ($newAttr == $psAttr) $newAttr = $psAttr+"UPP";
  626.         }
  627.         else
  628.         {
  629.             $newAttr = substitute( "PP", $psAttr, "VPP" );
  630.             if ($newAttr == $psAttr) $newAttr = $psAttr+"VPP";
  631.         }
  632.  
  633.  
  634.         // Use "Connect" if the attribute exists, otherwise
  635.         // use "Create".
  636.         //
  637.         if (AEattrDblExists( $psNode, $newAttr ))
  638.         {
  639.             menuItem
  640.                 -l ("Connect "+$newAttr+ " -> "+$amNode+"."+$amAttr)
  641.                 -c ("AEconnectAttrDoIt "+$psNode+" "+$newAttr+" "+$amNode+"."+$amAttr);
  642.         }
  643.         else
  644.         {
  645.             menuItem
  646.                 -l ("Create "+$newAttr+ " -> "+$amNode+"."+$amAttr)
  647.                 -c ("AEconnectAttrDoIt "+$psNode+" "+$newAttr+" "+$amNode+"."+$amAttr);
  648.         }
  649.     }
  650.  
  651.  
  652. }  // AEcreateConnectAttr //
  653.  
  654.  
  655.  
  656. //  ========== AEgenericCreateRamp ==========
  657. //
  658. //  Description
  659. //        Create a ramp node, an array mapper node, and make the
  660. //        necessary connections to the particle shape.
  661. //
  662.  
  663. global proc  AEgenericCreateRamp( string $node, string $attr, string $rowLyt )
  664. {
  665.     string    $cmd;
  666.  
  667.     $cmd = "arrayMapper -target "+$node+" -destAttr "+$attr+" -inputV ageNormalized -type ramp";
  668.     evalEcho( $cmd );
  669.  
  670.  
  671.     if (AEattrDblExists( $node, $attr ))
  672.     {
  673.         if (!`exists makeMonochromRampAMW`)
  674.         {
  675.             source ArrayMapperWnd;
  676.         }
  677.  
  678.         makeMonochromRampAMW( $node, $attr );
  679.     }
  680.  
  681.  
  682.     AEgenericUpdateOneTextfield( $node, $attr, $rowLyt );
  683.  
  684.  
  685. }  // AEgenericCreateRamp //
  686.  
  687.  
  688.  
  689. //  ========== AEgenericAttrPopupMenu ==========
  690. //
  691. //  Description:
  692. //        Build the popup menu for generic array attributes.
  693. //        The current state of the attribute determines what
  694. //        items are added to the menu. If the attribute is
  695. //        connected, then navigation items are added. If
  696. //        the attribute has an expression, then just the
  697. //        expression editor is available. If the attribute
  698. //        is not connected, then the default buttons are added.
  699. //
  700.  
  701. global proc  AEgenericAttrPopupMenu( string $parent, string $nodeName, string $attrName, string $attrType, string $rowLyt )
  702. {
  703.     string    $cnctAry[];
  704.     int        $cnctCnt;
  705.     string    $words[];
  706.     string    $amNode;
  707.     int        $deleteBtnOkay = 0;
  708.  
  709.  
  710.     // Delete the old buttons.
  711.     //
  712.     popupMenu -e -deleteAllItems $parent;
  713.     setParent -menu $parent;
  714.  
  715.  
  716.     // Check for upstream connections.
  717.     //
  718.     $cnctAry = `listConnections -s true -d false -p true ($nodeName+"."+$attrName)`;
  719.  
  720.     if (size( $cnctAry ))
  721.     {
  722.         tokenize( $cnctAry[0], ".", $words );
  723.  
  724.         if (AEgenericIsExpression( $cnctAry[0] ))
  725.         {
  726.             menuItem
  727.                 -l "Creation Expression..."
  728.                 -c ("expressionEditor creation "+$nodeName+" "+$attrName);
  729.  
  730.             menuItem
  731.                 -l "Runtime Expression..."
  732.                 -c ("expressionEditor runtime "+$nodeName+" "+$attrName);
  733.         }
  734.         else if (AEgenericIsArrayMapper( $cnctAry[0] ))
  735.         {
  736.             $amNode = $words[0];
  737.  
  738.             menuItem
  739.                 -l ("<- "+$cnctAry[0])
  740.                 -subMenu true;
  741.  
  742.             string    $ramp[] = `listConnections -s true -d false ($amNode+".computeNode")`;
  743.  
  744.             if (size( $ramp ) == 1)
  745.             {
  746.                 menuItem
  747.                     -l ("Edit Ramp")
  748.                     -c ("showEditor "+$ramp[0]);
  749.             }
  750.  
  751.             menuItem
  752.                 -l ("Edit Array Mapper")
  753.                 -c ("showEditor "+$amNode);
  754.  
  755.             AEcreateConnectAttr( $nodeName, $attrName, $amNode, "uCoordPP" );
  756.             AEcreateConnectAttr( $nodeName, $attrName, $amNode, "vCoordPP" );
  757.  
  758.             menuItem
  759.                 -l "Break Connection"
  760.                 -c ("AEgenericBreakAllConnections "+$nodeName+" "+$amNode );
  761.  
  762.             menuItem
  763.                 -l ("Delete Array Mapper")
  764.                 -c ("AEgenericDeleteMapper "+$nodeName+" "+$amNode+" "+$rowLyt);
  765.  
  766.             setParent -menu ..;
  767.         }
  768.         else
  769.         {
  770.             menuItem
  771.                 -l ("<- "+$cnctAry[0])
  772.                 -subMenu true;
  773.  
  774.             menuItem
  775.                 -l ("Edit "+$words[0])
  776.                 -c ("showEditor "+$words[0]);
  777.  
  778.             menuItem
  779.                 -l "Break Connection"
  780.                 -c ("AEgenericBreakConnection "+$nodeName+" "+$cnctAry[0]+" "+$nodeName+"."+$attrName);
  781.  
  782.             setParent -menu ..;
  783.         }
  784.     }
  785.  
  786.  
  787.     // When there are no upstream connections, add the default buttons
  788.     // regardless if there are any downstream connections.
  789.     //
  790.     else
  791.     {
  792.         // Do not allow expressions or component editor on the following:
  793.         // rampPosition, rampVelocity, rampAcceleration.
  794.         //
  795.         int $isNotRampAttr = 0;
  796.         if  ( ($attrName != "rampPosition") &&
  797.              ($attrName != "rampVelocity") &&
  798.              ($attrName != "rampAcceleration") )
  799.             $isNotRampAttr = 1;
  800.  
  801.         if ($isNotRampAttr)
  802.         {
  803.             menuItem
  804.                 -l "Creation Expression..."
  805.                 -c ("expressionEditor creation "+$nodeName+" "+$attrName);
  806.  
  807.             menuItem
  808.                 -l "Runtime Expression..."
  809.                 -c ("expressionEditor runtime "+$nodeName+" "+$attrName);
  810.         }
  811.  
  812.         // Do not allow ramp on the following attributes:
  813.         // lifespanPP, position, velocity, acceleration.
  814.         // Not possible to ramp these attributes.
  815.         //
  816.         int $isRampable = 1;
  817.  
  818.         if ( ($attrName != "lifespanPP") &&
  819.              ($attrName != "position") &&
  820.              ($attrName != "velocity") &&
  821.              ($attrName != "acceleration") )
  822.         {
  823.             menuItem 
  824.                 -l "Create Ramp"
  825.                 -c ("AEgenericCreateRamp "+$nodeName+" "+$attrName+" "+$rowLyt);
  826.             menuItem 
  827.                 -optionBox true
  828.                 -c ("ArrayMapperWnd "+$nodeName+" "+$attrName+" "+$rowLyt);
  829.         }
  830.  
  831.         // Also do not allow component editor on
  832.         // the ramp-specific attributes
  833.         //
  834.         if ($isNotRampAttr)
  835.         {
  836.             menuItem
  837.                 -l "Component Editor..."
  838.                 -c "componentEditorWindow";
  839.         }
  840.  
  841.         $deleteBtnOkay = 1;
  842.  
  843.         // Do not allow deleting lifespanPP (v 3.0 and after)
  844.         //
  845.         if ($attrName == "lifespanPP")
  846.             $deleteBtnOkay = 0;
  847.     }
  848.  
  849.  
  850.     // Add the standard navigation and disconnect buttons for all
  851.     // of the downstream connections.
  852.     //
  853.     $cnctAry = `listConnections -s false -d true -p true ($nodeName+"."+$attrName)`;
  854.     $cnctCnt = size( $cnctAry );
  855.  
  856.     if (size( $cnctAry ))
  857.     {
  858.         menuItem -divider true;
  859.  
  860.         for ($i = 0; $i < $cnctCnt; $i++)
  861.         {
  862.             tokenize( $cnctAry[$i], ".", $words );
  863.  
  864.             menuItem
  865.                 -l ("-> "+$cnctAry[$i])
  866.                 -subMenu true;
  867.  
  868.             menuItem
  869.                 -l ("Edit "+$words[0])
  870.                 -c ("showEditor "+$words[0]);
  871.  
  872.             menuItem
  873.                 -l "Break Connection"
  874.                 -c ("AEgenericBreakConnection "+$nodeName+" "+$nodeName+"."+$attrName+" "+$cnctAry[$i]);
  875.  
  876.             setParent -menu ..;
  877.         }
  878.     }
  879.     else
  880.     {
  881.         if ($deleteBtnOkay)
  882.         {
  883.             if (AEokayAttr( $nodeName, $attrName ))
  884.             {
  885.                 menuItem
  886.                     -l "Delete Attribute"
  887.                     -c ("AEgenericDeleteAttr "+$nodeName+" "+$attrName);
  888.             }
  889.         }
  890.     }
  891.  
  892.  
  893. }  // AEgenericAttrPopupMenu //
  894.  
  895.  
  896.  
  897. //  ========== AEaddUI ==========
  898. //
  899. //  Description:
  900. //        Create new ui for the array attribute, and add 
  901. //        it to the layout. This creates a label, a read-only
  902. //        textfield, and registers the callback for the popup menu.
  903. //
  904.  
  905. proc  AEaddUI( string $nodeName, string $attrNameType )
  906. {
  907.     global int $gTextColumnWidthIndex;
  908.  
  909.     string    $words[]; tokenize( $attrNameType, ".", $words );
  910.     string    $attrName = $words[0];
  911.     string    $attrType = $words[1];
  912.     string    $uiName = $attrName;    // replace this with listAttr cmd
  913.     string  $annotation = "";
  914.     if ($uiName == "worldVelocityInObjectSpace") {
  915.         $uiName = "worldVelocity";
  916.         $annotation = "World Velocity In Object Space";
  917.     }
  918.  
  919.     // Make sure the parent is selected.
  920.     //
  921.     global string    $gAEgenericColumnLayout;
  922.  
  923.     setParent $gAEgenericColumnLayout;
  924.  
  925.  
  926.     // Make a unique name for the layout. Cannot use attribute name,
  927.     // because the layouts are reused. Use the child count instead.
  928.     //
  929.     int        $childCnt = `columnLayout -q -numberOfChildren $gAEgenericColumnLayout`;
  930.     string    $lytName = "DynAryAttrRowLayout"+$childCnt;
  931.  
  932.  
  933.     // Add the new buttons.
  934.     //
  935.     setUITemplate -pst attributeEditorPresetsTemplate;
  936.  
  937.     rowLayout 
  938.         -nc 3 -vis 0
  939.         -columnWidth 1 $gTextColumnWidthIndex
  940.         -columnWidth 2 238
  941.         -columnAttach 2 both 0
  942.         -columnAttach 1 right 5
  943.         $lytName;
  944.  
  945.     if ($annotation == "") {
  946.         text -l $uiName;
  947.     } else {
  948.         text -l $uiName -annotation $annotation;        
  949.     }
  950.  
  951.         string    $text = AEgenericConnectText( $nodeName, $attrName );
  952.         textField -tx $text -editable false  ("ExprField"+$childCnt);
  953.         string    $menuName = "ExprField"+$childCnt+"Menu";
  954.         popupMenu 
  955.             -allowOptionBoxes true
  956.             -postMenuCommand ("AEgenericAttrPopupMenu "+$menuName+" "+$nodeName+" "+$attrName+" "+$attrType+" "+$lytName)
  957.             $menuName;
  958.  
  959.         setParent ..;
  960.  
  961.     rowLayout -e -vis 1 $lytName;
  962.  
  963.     string $plugName = $nodeName+"."+$attrName;
  964.     scriptJob -p $lytName -rp -con $plugName ("AEgenericUpdateAllTextfields \""+$nodeName+"\"");
  965.  
  966.     setUITemplate -ppt;
  967.  
  968.  
  969. }  // AEaddUI //
  970.  
  971.  
  972.  
  973. //  ========== AEreplaceUI ==========
  974. //
  975. //  Description:
  976. //        Replace the current ui with new labels and callbacks.
  977. //
  978.  
  979. proc  AEreplaceUI( string $nodeName, string $attrNameType, string $rowLyt )
  980. {
  981.     string    $childAry[] = `rowLayout -q -childArray $rowLyt`;
  982.     string    $words[]; tokenize( $attrNameType, ".", $words );
  983.     string    $name = $words[0];
  984.     string    $type = $words[1];
  985.     string    $uiName = $name;    // RAMS replace this with listAttr cmd
  986.     string  $annotation = "";
  987.  
  988.     if ($uiName == "worldVelocityInObjectSpace") {
  989.         $uiName = "worldVelocity";
  990.         $annotation = "World Velocity In Object Space";
  991.     }
  992.     setParent $rowLyt;
  993.     text -e -l $uiName $childAry[0];
  994.     if ($annotation != "") {
  995.         text -e -annotation $annotation $childAry[0];
  996.     }
  997.     AEgenericUpdateOneTextfield( $nodeName, $name, $rowLyt );
  998.     popupMenu -e -pmc ("AEgenericAttrPopupMenu "+$childAry[1]+"Menu "+$nodeName+" "+$name+" "+$type+" "+$rowLyt) ($childAry[1]+"Menu");
  999.     string $plugName = $nodeName+"."+$name;
  1000.     scriptJob -p $rowLyt -rp -con $plugName ("AEgenericUpdateAllTextfields \""+$nodeName+"\"");
  1001.  
  1002. }  // AEreplaceUI //
  1003.  
  1004.  
  1005.  
  1006. //  ========== AEgenericPerParticle ==========
  1007. //
  1008. //  Description:
  1009. //        Called whenever the Attribute Editor is building or updating the 
  1010. //        Per Particle Attribute layout.
  1011. //
  1012.  
  1013. global proc  AEgenericPerParticle( string $unused, string $nodeAttr )
  1014. {
  1015.     string    $words[]; tokenize( $nodeAttr, ".", $words );
  1016.     string    $nodeName = $words[0];
  1017.  
  1018.  
  1019.     // Make sure the correct parent layout names have been saved.
  1020.     //
  1021.     global string    $gAEgenericColumnLayout;
  1022.     global string    $gAEgenericFrameLayout;
  1023.  
  1024.     AEgenericReset();
  1025.  
  1026.  
  1027.     // Get sorted list of dynamic array attributes and list
  1028.     // of existing rowColumn layouts for array attributes.
  1029.     //
  1030.     string    $attrList[];
  1031.     string    $rowLytAry[];
  1032.  
  1033.     AEdynAryAttr( $nodeName, $attrList );
  1034.     $rowLytAry = `columnLayout -q -childArray $gAEgenericColumnLayout`;
  1035.  
  1036.     // Update the ui. Reuse the existing widgets before creating
  1037.     // new ones. The extra layouts will be deleted later.
  1038.     //
  1039.     int        $attrCnt = size( $attrList );
  1040.     int        $rcCnt = size( $rowLytAry );
  1041.  
  1042.     for ($i = 0; $i < $attrCnt; $i++)
  1043.     {
  1044.         if ($i < $rcCnt)
  1045.         {
  1046.             AEreplaceUI( $nodeName, $attrList[$i], $rowLytAry[$i] );
  1047.         }
  1048.         else
  1049.         {
  1050.             AEaddUI( $nodeName, $attrList[$i] );
  1051.         }
  1052.     }
  1053.  
  1054.     // Delete any extra layouts that are no longer needed.
  1055.     //
  1056.     if ($attrCnt < $rcCnt)
  1057.     {
  1058.         for ($i = $rcCnt - 1; $i >= $attrCnt; $i--)
  1059.         {
  1060.             deleteUI -layout $rowLytAry[$i];
  1061.         }
  1062.     }
  1063.  
  1064.  
  1065.     // Expand the Per Particle Attribute panel to make sure
  1066.     // the user can find the new attributes.
  1067.     //
  1068.     if (size( $gAEgenericColumnLayout ))
  1069.     {
  1070.         frameLayout -e -collapse 0 $gAEgenericFrameLayout;
  1071.     }
  1072.  
  1073.  
  1074. }  // AEgenericPerParticle //
  1075.